#!/usr/bin/env bash
#===========HEADER===========================================================|
#AUTOR
# Jefferson Rocha <lrcjefferson@gmail.com
#
#PROGRAMA
# shan - Shell Archive Network
#
#HOMEPAGE
# shan.slackjeff.com.br
#============================================================================|

#======VARS=============================|
readonly NAME="shan"
readonly VERSION="0.1beta"
readonly AUTHOR="Jefferson Rocha <lrcjefferson@gmail.com>" # Autor do programa
readonly STRIP="strip.txt"                                 # Strip localizado na origem
readonly REPO="REPO.txt"                                   # Lista de módulos disponivel
readonly LOG_ERROR="/home/${USER}/shan/tmp/error.log"

#=DIRECTORYS
export DIRECTORYS
DIRECTORYS=( # Lista de diretorios
      "/home/${USER}/shan/"
      "/home/${USER}/shan/core/"
      "/home/${USER}/shan/bin/"
      "/home/${USER}/shan/conf/"
      "/home/${USER}/shan/tmp/"
      "/home/${USER}/shan/modules/"
      "/home/${USER}/shan/trash/"
)
#=======================================|

#======TESTS============================|
# Diretorios existem?
for dir in "${DIRECTORYS[@]}"; do
    if [ ! -d "$dir" ]; then
       printf '%b' "-------- Diretório ${dir} NÃO EXISTE! ABORTANDO.\n"
       exit 1
    fi
done

if [ ! -e "${DIRECTORYS[3]}${REPO}" ]; then
   printf "Primeira vez? use update no modo interativo ou ${NAME} update para atualizar o REPO.\n\n"
fi
#======================================|

#======LIBS=============================|
. "${DIRECTORYS[3]}${NAME}.conf" # Arquivo de configuração
#=======================================|

#======FUNC=============================|

die(){ printf '%-65s[ERRO]\n' "$*" 1>&2 ; continue ;}

USAGE()
{
cat <<END
${NAME} - Shell Archive Network
Gerenciador de módulos Shell.

OPÇÕES:
   help, h, ?
       Mostra este manual e sai.

   update
       Faz update do repositório oficial do ${NAME}.
       Não precisa ser passado argumentos.

   search
       Busca por um módulo específico. O padrão necessita ser
       CATEGORIA%MÓDULO, ou seja a categoria e depois o nome do módulo.
       O padrão é usar o % para fazer a divisão da categoria para nome
       do módulo. Os nomes dos módulos jamais possuem traços ou caracteres
       especiais, com exceção do _ Underline que substitui o espaço.

       Exemplos:
       search util%colorize
       search debug%depurator
       search network%net_verify 
     
   install
       Faz a instalação de um módulo específico e sua árvore atráves
       do repositório oficial do ${NAME}.
       O padrão necesita ser CATEGORIA%MÓDULO, expressões regulares REGEX
       não funcionam.

       Exemplos:
       install util%colorize
       install debug%depurator
       install network%net_verify   
   
   clear
      Limpa os arquivos enviados para a lixeira do ${NAME}.
      Não há argumento para ser passado.

   view
      Visualiza as informações do módulo passado como argumento.
      Não há necessidade de passar a categoria e sim apenas o nome
      do módulo.

      Exemplo:
      view colorize
      view depurator
      view net_verify

   version
      Mostra a versão do ${NAME}.
END
}

UPDATE()
{
     (cd "${DIRECTORYS[3]}"; wget --quiet --show-progress --output-document="${REPO}" "${LINK_REPO}")
}

SEARCH()
{
     [ -z "$argument2" ] && { printf '%b' "Null.\n"; return 1; } # Entrada nula? retorna.
     ( # Abrindo subshell para executar cd e grep e utilitarios para não sujar processo pai.
      cd "${DIRECTORYS[3]}"
      archive=$(grep -w "^${argument2}$" "$REPO")
      if [ -z "$archive" ]; then  # Var está nula?
         printf "Módulo: ${argument2}, Não foi encontrado.\n"
         return 1
      fi 
      printf '%b' "${archive}\n"
     )
}

INSTALL()
{
     [ -z "$argument2" ] && { printf '%b' "Null.\n"; return 1; } # Entrada nula? retorna.
     # Metacaracteres '.*' não serão legais na hora de instalar!
     # Se existir vamos trocar por nada.
     argument2=$(echo "$argument2" | tr '.*' ' ')
     ( # Abrindo subshell para executar cd e grep e utilitarios para não sujar processo pai.
      cd "${DIRECTORYS[3]}"
      archive=$(grep -w "^${argument2}$" "$REPO" 2>/dev/null)
      if [ -z "$archive" ]; then  # Var está nula?
         printf "Módulo: ${argument2}, Não foi encontrado.\n"
         return 1
      fi
      # Obtendo campos CATEGORIA E MODULO
      CATEGORY=$(echo "$archive" | cut -d '%' -f '1')
      MODULE=$(echo "$archive" | cut -d '%' -f '2')
     
      # Mirror para download do STRIP
      MIRROR1="https://notabug.org/SHAN/REPOSITORY/raw/master/${CATEGORY}/${MODULE}/"
      cd "${DIRECTORYS[5]}"
      [ ! -d "$MODULE" ] && mkdir "$MODULE"
      cd "$MODULE" 1>/dev/null 2>/dev/null || die "impossível entrar em ${MODULE}\n"
     
      printf "+++++++++ Iniciando Download...\n"

      # Download do Strip
      wget --quiet --show-progress --output-document="strip.txt" "${MIRROR1}${STRIP}" || die "impossível baixar ${STRIP}."

      # Carregando Strip para obter dados nas variáveis.
      . "${DIRECTORYS[5]}${MODULE}/${STRIP}"

      # Download da Descrição
      wget --quiet --show-progress --output-document="description.txt" "${DESCRIPTION}" || die "impossível baixar ${DESCRIPTION}."

      #Entrando em shan/tmp para baixar MD5 e Módulo.tar.gz
      #para fazer a conferencia!
      cd "${DIRECTORYS[4]}" || die "Impossível entrar em ${DIRECTORYS[4]}"

      # Download do MD5
      wget --quiet --show-progress --output-document="${name}-${version}.md5" "${MD5}" || die "impossível baixar ${DESCRIPTION}."

      # Download do Modulo.tar.gz
      wget --quiet --show-progress --output-document="${name}-${version}.tar.gz" "${SOURCE}" || die "impossível baixar ${DESCRIPTION}."

      printf '%-65s[OK]\n' "Download Concluído com SUCESSO!"

      # Conferencia de MD5
      printf "\n+++++++++ Conferência do ${name}-${version}.tar.gz\n"
      if ! md5sum --quiet -c "${name}-${version}.md5" 2>/dev/null; then
         printf '%-65s[ERRO]\n' "${name}-${version}.tar.gz MD5 não bateu!"
         if mv -v "${name}-${version}.tar.gz" "${name}-${version}.md5" "${DIRECTORYS[6]}"; then # Movendo pacotes para LIXO!
            printf "Pacote enviado para ${DIRECTORYS[6]} para sua análise!\n"
            return 1
         else
            printf '%-65s[ERRO]\n' "Impossível mover ${name}-${version}.tar.gz e .md5 para ${DIRECTORYS[6]}"
            return 1
         fi
      else
         printf '%-65s[OK]\n' "${name}-${version}.tar.gz"
         # Ok! vamos mover...
         printf "\n+++++++++ Movendo para destino final em ${DIRECTORYS[5]}${name}/\n"
         if ! mv "${name}-${version}.tar.gz" "${name}-${version}.md5" "${DIRECTORYS[5]}${name}/"; then
            printf '%-65s[ERRO]\n' "Impossível mover ${name}-${version}.tar.gz E ${name}-${version}.md5 para ${DIRECTORYS[5]}${name}/"
            return 1
         else
            # Entrando no diretório do módulo
            cd "${DIRECTORYS[5]}${name}/" || die "Impossível entrar em ${DIRECTORYS[5]}${name}/"
            # Arquivo .tar.gz existe?
            [ ! -e "${name}-${version}.tar.gz" ] && die "${name}-${version}.tar.gz Não existe."
            printf "\n+++++++++ Desempacotando ${name}-${version}.tar.gz\n"
            # Descompactando
            tar xf "${name}-${version}.tar.gz" || die "Houve um erro ao tentar desempacotar ${name}-${version}.tar.gz"
            # Removendo arquivos .tar.gz e .md5
            rm "${name}-${version}.tar.gz" "${name}-${version}.md5" 1> /dev/null 2> /dev/null
            printf "Módulo ${name} instalado com sucesso!\n"
         fi
      fi
     )
}

CLEAR()
{   
    ( #Abrindo Subshell
     cd "${DIRECTORYS[6]}" || die "Impossível entrar em ${DIRECTORYS[6]}"
     printf '%-50s[WAIT]\n' "\n+++++++++ Listagem da lixeira"
     for "list" in *; do
          printf '%b' "----> ${list}\n"
     done
     printf '%b' "\nDeseja limpar o diretório ${DIRECTORYS[6]}? [Y/n] "
     read option
     option="${option:=Y}"                         # Apertou enter é Y!
     option=$(echo "$option" | tr '[A-Z]' '[a-z]') # Tudo em maiusculo
     [ "$option" = "y" ] && rm -v - * || return 0
    ) 
}

VIEW()
{
    [ -z "$argument2" ] && { printf '%b' "Null.\n"; return 1; } # Entrada nula? retorna.
    ( # Abrindo Subshell
     cd "${DIRECTORYS[5]}${argument2}" || die "Módulo não encontrado!"
        if ! cat -n "description.txt" 2> /dev/null; then
           printf '%b' "Impossível carregar description.txt\n"
           return 1
        fi
    )
}
#=======================================|

# Conferindo se o usuário passou parâmetros.
if [ "$1" = "update" ]; then
   UPDATE
   exit 0
fi

#++++++++++++++++++++
# Chamada Principal!
#++++++++++++++++++++
msg="Bem vindo ao SHELL ARCHIVE NETWORK, versão ${VERSION}."
cat <<END
${msg}
Para ajuda digite 'h', 'help', '?'.

END
underline=$(tput smul)
end=$(tput sgr0)
while :; do
   printf '%s' "${underline}${NAME}>>${end} "; read argument argument2
   argument="${argument:=null}" # Nulo?
   case "$argument" in
      h|help|\?) USAGE       ;;
      update)    UPDATE      ;;
      search)    SEARCH      ;;
      install)   INSTALL     ;;
      clear)     CLEAR       ;;
      view)      VIEW        ;;
      version)   printf '%b' "${NAME} VERSÃO ${VERSION}\n"      ;;
      null)      continue    ;;
      *) printf '%b' "Para ajuda digite 'h', 'help', '?'.\n"    ;;
   esac
done
